using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace SPListGuidPrint
{
    class Program
    {
        static List<string> builtInStaticTitles = new List<string>();

        public class ListItem
        {
            public string name = string.Empty;
            public string type = string.Empty;
            public string resultType = string.Empty;
            public string guid = string.Empty;
        };

        static List<ListItem> listItems = new List<ListItem>();
        static string listTitle = string.Empty;
        static System.IO.StreamWriter file = null;

        private static void SetBuiltInTitles()
        {
            builtInStaticTitles.Add("_ModerationComments");
            builtInStaticTitles.Add("SelectTitle");
            builtInStaticTitles.Add("Edit");
            builtInStaticTitles.Add("FileRef");
            builtInStaticTitles.Add("FileDirRef");
            builtInStaticTitles.Add("Last_x0020_Modified");
            builtInStaticTitles.Add("Created_x0020_Date");
            builtInStaticTitles.Add("FSObjType");
            builtInStaticTitles.Add("PermMask");
            builtInStaticTitles.Add("FileLeafRef");
            builtInStaticTitles.Add("UniqueId");
            builtInStaticTitles.Add("ProgId");
            builtInStaticTitles.Add("ScopeId");
            builtInStaticTitles.Add("HTML_x0020_File_x0020_Type");
            builtInStaticTitles.Add("_EditMenuTableStart");
            builtInStaticTitles.Add("_EditMenuTableEnd");
            builtInStaticTitles.Add("LinkFilenameNoMenu");
            builtInStaticTitles.Add("LinkFilename");
            builtInStaticTitles.Add("DocIcon");
            builtInStaticTitles.Add("ServerUrl");
            builtInStaticTitles.Add("EncodedAbsUrl");
            builtInStaticTitles.Add("BaseName");
            builtInStaticTitles.Add("MetaInfo");
            builtInStaticTitles.Add("_Level");
            builtInStaticTitles.Add("_IsCurrentVersion");
            builtInStaticTitles.Add("File_x0020_Type");
        }

        private static void SetCType(ListItem item, out string cType, out string cTypeDefault)
        {
            if (item.type.Contains("Text") || item.resultType.Contains("Text") )
            {
                cType = "string";
                cTypeDefault = "string.Empty";
            }
            else if (item.type.Contains("Number") || item.resultType.Contains("Number"))
            {
                cType = "int";
                cTypeDefault = "0";
            }
            else if (item.type.Contains("DateTime") || item.resultType.Contains("DateTime"))
            {
                cType = "DateTime";
                cTypeDefault = "null";
            }
            else
            {
                cType = item.type;
                cTypeDefault = "null";
            }
        }

        private static void WriteLine(string line)
        {
            Console.WriteLine(line);
            file.WriteLine(line);
        }

        static void Main(string[] args)
        {
            SetBuiltInTitles();

            Console.Write("Please enter path to manifest.xml: ");
            string xmlPath = Console.ReadLine();
            // xmlPath = static path

            // Be sure to set a reference to System.Core and System.Xml.Linq 
            XElement manifest  = XElement.Load(xmlPath);

            if (manifest == null)
            {
                Console.WriteLine("Path is invalid:" + xmlPath);
                return;
            }

            string outputFilePath = xmlPath.Substring(0, xmlPath.Length - 4) + "_guids.txt";
            file = new System.IO.StreamWriter(outputFilePath);

            Console.WriteLine();

            var list =
                (from XElement l in manifest.
                        Descendants("UserLists").
                        Descendants("List")
                select l).FirstOrDefault();

            if (list.Attribute("Title") != null)
            {
                listTitle = list.Attribute("Title").Value;
                WriteLine("public class " + listTitle);
                WriteLine("{");
            }

            // Using LINQ to select the fields
            var fields = 
                from XElement f in manifest.
                                    Descendants("UserLists").
                                    Descendants("List").
                                    Descendants("MetaData").
                                    Descendants("Fields").
                                    Descendants("Field")                                    
                select f; 

            // Build the list of Fields, omitting the built in ones
            foreach(XElement field in fields)
            {
                XAttribute guid = field.Attribute("ID");
                XAttribute displayName = field.Attribute("DisplayName");
                XAttribute colName = field.Attribute("ColName");
                XAttribute staticName = field.Attribute("StaticName");
                XAttribute type = field.Attribute("Type");
                XAttribute resultType = field.Attribute("ResultType");

                if(colName != null && colName.Value.Substring(0, 3).Contains("tp_"))
                    continue;

                if (staticName != null &&
                   builtInStaticTitles.Contains(staticName.Value))
                    continue;                

                if (guid != null && displayName != null)
                {
                    ListItem item = new ListItem();
                    item.name = displayName.Value.Replace(' ', '_');
                    item.guid = guid.Value;
                    item.type = (type == null) ? "" : type.Value;
                    item.resultType = (resultType == null) ? "" : resultType.Value;

                    listItems.Add(item);
                }
            }

            // print results to Console & File

            // print Guids section
            WriteLine("");
            WriteLine("\t#region Guids");
            WriteLine("");
            foreach (ListItem item in listItems)
            {
                WriteLine(
                    string.Format("\t\tGuid {0}_ID = new Guid(\"{1}\");",
                        item.name,
                        item.guid )
                        );
            }
            WriteLine("");
            WriteLine("\t#endregion");
            WriteLine("");

            // print variables section
            WriteLine("");
            WriteLine("\t#region Variables");
            WriteLine("");
            foreach (ListItem item in listItems)
            {
                string cType;
                string cTypeDefault;

                SetCType(item, out cType, out cTypeDefault);

                WriteLine(
                    string.Format("\t\tpublic {0} {1} = {2};",
                        cType,
                        item.name,
                        cTypeDefault)
                        );
            }
            WriteLine("");
            WriteLine("\t#endregion");
            WriteLine("");

            if (!string.IsNullOrEmpty(listTitle))
            {
                WriteLine("}");
            }

            file.Close();

            Console.WriteLine("Press a key to continue...");
            Console.ReadKey();
        }
    }
}
